import xml.etree.ElementTree as ET
import numpy as np


# 读取dataxml中的所有floor的上、下表面的高度
def get_dataxml_height(dataXml):
    tree = ET.parse(dataXml)
    root = tree.getroot()
    entitys = root.find('Entitys')
    floor_height = []
    for entity in entitys:
        if entity.tag == "Entity":
            if entity.attrib['type'] == 'Floor':
                # print(entity.attrib['UniqueId'])
                sectionEntitys = entity.findall('SectionEntity')
                flag = True
                for sectionEntity in sectionEntitys:
                    if sectionEntity.attrib['Points'] == '' or sectionEntity.attrib['Points'] == '':
                        flag = False
                        break
                    if sectionEntity.attrib['description'] == 'TopFace':
                        topface_height = float(sectionEntity.attrib['Points'].split(';')[0].split(',')[-1]) 
                    if sectionEntity.attrib['description'] == 'BottomFace':
                        bottomface_height = float(sectionEntity.attrib['Points'].split(';')[0].split(',')[-1])
                if flag:
                    floor_height.append([topface_height, bottomface_height])
    return floor_height


def topface_height_judge(floor_group_height, height):
    #  np.mean(floor_group_height, axis=0)为上下表面的平均值
    if abs(np.mean(floor_group_height, axis=0)[0] - height) <= 1000:
        return True
    else:
        return False


# 按照上表面的高度，将这些高度分为多组
def divide_floor_height(dataXml):
    all_floor_height = get_dataxml_height(dataXml)
    floor_groups = []
    if not all_floor_height:
        return floor_groups
    for height in all_floor_height:
        if floor_groups:
            flag = 1
            for floor_group in floor_groups:
                if topface_height_judge(floor_group, height[0]):
                    floor_group.append(height)
                    flag = 0
            if flag == 1:
                floor_groups.append([height])
        else:
            floor_groups.append([height])
    return floor_groups


def uniform_floor_height(floor_groups):
    xml_floor_height = xml_true_ceiling_height = 0
    if len(floor_groups) == 1:
        xml_floor_height = np.median(floor_groups[0], axis=0)[0]
        # 取地板的上沿
    elif len(floor_groups) == 2:
        # 判断哪组是天花板哪组是地板
        if np.mean(floor_groups[0]) > np.mean(floor_groups[1]):
            xml_true_ceiling_height = np.median(floor_groups[0], axis=0)[1]
            xml_floor_height = np.median(floor_groups[1], axis=0)[0]
            # 取天花板的下沿
        else:
            xml_true_ceiling_height = np.median(floor_groups[1], axis=0)[1]
            xml_floor_height = np.median(floor_groups[0], axis=0)[0]
    elif len(floor_groups) >= 3:
        min_floor_group = float('inf')
        # 找到最低的作为地板高度
        index = 0
        for floor_group in floor_groups:
            average_floor_height = np.mean(floor_group, axis=0)[0]
            if min_floor_group > average_floor_height:
                min_floor_group = average_floor_height
                index = floor_groups.index(floor_group)
        xml_floor_height = np.median(floor_groups[index], axis=0)[0]
        # 和地板距离最靠近4.5m的作为真天花
        min_height_difference = abs(np.mean(floor_groups[0], axis=0)[1] - xml_floor_height - 4500)
        index = 0
        for floor_group in floor_groups:
            average_true_floor_height = np.mean(floor_group, axis=0)[1]
            if min_height_difference > abs(average_true_floor_height - xml_floor_height - 4500):
                min_height_difference = abs(average_true_floor_height - xml_floor_height - 4500)
                index = floor_groups.index(floor_group)
        xml_true_ceiling_height = np.median(floor_groups[index], axis=0)[1]
    return xml_floor_height, xml_true_ceiling_height


# print(uniform_floor_height(   [[[1000,1200],[1000,1200]],[[2000,2200],[2000,2200]],[[4000,4200],[4000,4200]]]    ))


def get_floor_height(dataXml, configXml):
    floor_height = false_ceiling_height = true_ceiling_height = 0
    floor_groups = divide_floor_height(dataXml)  # dataxml中的高度
    print("读到" + str(len(floor_groups)) + "组楼板")
    ui_floor_height, ui_false_ceiling_height, ui_true_ceiling_height = get_configxml_height(configXml)  # configxml中的高度
    if len(floor_groups) == 0:
        # dataxml中没有floor标签
        # if ui_floor_height is None and ui_false_ceiling_height is None and ui_true_ceiling_height is None:
            # ui中三个高度全没有输入
        floor_height = 0
        # false_ceiling_height = 3000
        # true_ceiling_height = 4500
        false_ceiling_height = -float('inf')
        true_ceiling_height = float('inf')
        print('dataxml未读取到地板和天花板，ui未输入，返回默认高度，地板%s 假天花%s 真天花%s' % (floor_height,
                                                                    false_ceiling_height + floor_height,
                                                                    true_ceiling_height + floor_height))
        return floor_height, false_ceiling_height + floor_height, true_ceiling_height + floor_height, False
        # elif ui_floor_height is None and ui_true_ceiling_height is None and ui_false_ceiling_height is not None:
        #     # ui中只输入了必填的假天花高度
        #     floor_height = 0
        #     true_ceiling_height = 4500
        #     return floor_height, int(ui_false_ceiling_height) + floor_height, true_ceiling_height + floor_height, False
        # elif ui_floor_height is not None and ui_true_ceiling_height is not None and ui_false_ceiling_height is not None:
        #     # ui中三个高度全部输入
        #     return int(ui_floor_height), int(ui_false_ceiling_height) + int(ui_floor_height), int(ui_true_ceiling_height) + int(ui_floor_height), True
    elif len(floor_groups) == 1:
        # dataxml中读到一层楼板,认为这层为地板
        floor_height, _ = uniform_floor_height(floor_groups)
        if ui_false_ceiling_height is None and ui_true_ceiling_height is None:
            false_ceiling_height = 2800
            true_ceiling_height = 4500
            print('dataxml未读取一组楼板，认为是地板，ui未输入，地板%s 假天花%s 真天花%s' % (floor_height,
                                                                         false_ceiling_height + floor_height,
                                                                         true_ceiling_height + floor_height))
            return floor_height, false_ceiling_height + floor_height, true_ceiling_height + floor_height, True
        elif ui_false_ceiling_height is not None and ui_true_ceiling_height is not None:
            return floor_height, int(ui_false_ceiling_height) + floor_height, int(ui_true_ceiling_height) + floor_height, True
        elif ui_false_ceiling_height is not None and ui_true_ceiling_height is None:
            true_ceiling_height = 4500
            return floor_height, int(ui_false_ceiling_height) + floor_height, true_ceiling_height + floor_height, True
    elif len(floor_groups) == 2:
        floor_height, true_ceiling_height = uniform_floor_height(floor_groups)
        if ui_false_ceiling_height is None:
            ui_false_ceiling_height = 2800
        return floor_height, int(ui_false_ceiling_height) + floor_height, true_ceiling_height, True
    else:
        # 读到三组和以上楼板
        floor_height, true_ceiling_height = uniform_floor_height(floor_groups)
        if ui_false_ceiling_height is None:
            ui_false_ceiling_height = 2800
        return floor_height, int(ui_false_ceiling_height) + floor_height, true_ceiling_height, True


def get_configxml_height(configXml):
    tree = ET.parse(configXml)
    root = tree.getroot()
    false_ceiling_height = root.find('OtherSettings').find('GlobalFalseCeiling').find('height').text
    true_ceiling_height = None
    floor_height = None
    return floor_height, false_ceiling_height, true_ceiling_height


if __name__ == '__main__':
    print('地板%s 假天花%s 真天花%s flag%s' % (get_floor_height("C:/revit_data/1196/revit_data.xml",
                                                 'C:/revit_data/1196/user_config.xml')))
